package com.xyzk.diagnose.tools;

import java.util.Random;


public class VinToPin {
	public static final String JAC_KEY = "11111001";
	public static final String ZOTYE_KEY="11111002";
	private static final int DESNUM = 8;
	private static boolean Is3DES;// 3次DES标志
	private static byte[] SubKey = new byte[32 * 48];
	private static byte[] deskey = new byte[16];
	private static byte[] Tmp = new byte[256];
	private static byte[] IP_Table = {
			58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
			62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
			57, 49, 41, 33, 25, 17,  9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
			61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
	};
	private static byte[] IPR_Table = {
			40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
			38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
			36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
			34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41,  9, 49, 17, 57, 25
	};
	private static byte[] E_Table = {
			32,  1,  2,  3,  4,  5,  4,  5,  6,  7,  8,  9,
			8,  9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17,
			16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,
			24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32,  1
	};
	private static byte[] P_Table = {
			16, 7, 20, 21, 29, 12, 28, 17, 1,  15, 23, 26, 5,  18, 31, 10,
			2,  8, 24, 14, 32, 27, 3,  9,  19, 13, 30, 6,  22, 11, 4,  25
	};
	private static byte[] PC1_Table = {
			57, 49, 41, 33, 25, 17,  9,  1, 58, 50, 42, 34, 26, 18,
			10,  2, 59, 51, 43, 35, 27, 19, 11,  3, 60, 52, 44, 36,
			63, 55, 47, 39, 31, 23, 15,  7, 62, 54, 46, 38, 30, 22,
			14,  6, 61, 53, 45, 37, 29, 21, 13,  5, 28, 20, 12,  4
	};
	private static byte[] PC2_Table = {
			14, 17, 11, 24,  1,  5,  3, 28, 15,  6, 21, 10,
			23, 19, 12,  4, 26,  8, 16,  7, 27, 20, 13,  2,
			41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
			44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
	};
	private static byte[] LOOP_Table = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};
	//8 * 4* 16
	private static byte[] S_Box = {
			// S1
			14,4,	13,	 1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
			0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
			4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
			15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13,
			// S2
			15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
			3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
			0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
			13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9,
			// S3
			10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
			13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
			13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
			1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12,
			// S4
			7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
			13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
			10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
			3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14,
			// S5
			2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
			14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
			4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
			11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3,
			// S6
			12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
			10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
			9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
			4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13,
			// S7
			4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
			13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
			1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
			6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12,
			// S8
			13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
			1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
			7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
			2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
	};

	/**
	 * S盒
	 */
	static final int S_BOX[][] = { {0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76},
			{0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0},
			{0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15},
			{0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75},
			{0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84},
			{0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf},
			{0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8},
			{0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2},
			{0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73},
			{0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb},
			{0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79},
			{0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08},
			{0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a},
			{0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e},
			{0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf},
			{0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16} };

	/**
	 * 逆S盒
	 */
	static final int INVERSE_S_BOX[][] = { {0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb},
			{0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb},
			{0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e},
			{0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25},
			{0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92},
			{0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84},
			{0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06},
			{0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b},
			{0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73},
			{0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e},
			{0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b},
			{0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4},
			{0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f},
			{0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef},
			{0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61},
			{0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d}};

	static int RC[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};

	//巢湖生成PIN
	public static void cheryVinToPin(String vin, byte []pin){
		aes(vin,pin,"Chery_xinnengyuan_vintopin_12345");
	}

	public static void aes(String vin, byte []pin,String password){
		String passwordhex="43686572795F78696E6E656E677975616E5F76696E746F70696E5F3132333435";
		//		str2hex(password,passwordhex);
		int p[][]=new int[4][4];
		for (int m = 0; m < 4; ++m) {
			for (int i = 0; i < 4; ++i) {
				int indx = 4 * i + m;
				p[i][m] = 16 * c2i(passwordhex.charAt(indx)) + c2i(passwordhex.charAt(indx + 1));
			}
		}
		char []content = new char[33];
		for(int i=0;i<vin.length();i++){
			content[i]=vin.charAt(i);
		}

		//必须是16位，填充VIN前15位
		for (int j = 17; j < 32; ++j) {
			content[j] = vin.charAt(j - 17);
		}

		//存储结果
		char []encry = new char[33];
		//将文件转换成16字节的int型数组加密、解密
		for (int i = 0; i < 2; ++i) {

			int content_to_int[][]=new int[4][4];
			for (int j = 0; j < 4; ++j) {
				for (int k = 0; k < 4; ++k) {
					content_to_int[j][k] = content[j * 4 + k + 16 * i];
				}
			}
			aes_detail(content_to_int, p);
			for (int j = 0; j < 4; ++j) {
				for (int k = 0; k < 4; ++k) {
					encry[j * 4 + k + 16 * i] = (char) content_to_int[j][k];
				}
			}
		}
		pin[0]=(byte) encry[30];
		pin[1]=(byte) encry[31];
	}

	//将字符转换为数值
	static int c2i(char ch) {
		// 如果是数字，则用数字的ASCII码减去48, 如果ch = '2' ,则 '2' - 48 = 2
		if(ch>='0'&&ch<='9')
			return ch - 48;

		// 如果是字母，但不是A~F,a~f则返回
		if( ch < 'A' || (ch > 'F' && ch < 'a') || ch > 'z' )
			return -1;

		// 如果是大写字母，则用数字的ASCII码减去55, 如果ch = 'A' ,则 'A' - 55 = 10
		// 如果是小写字母，则用数字的ASCII码减去87, 如果ch = 'a' ,则 'a' - 87 = 10
		if(ch>='A'&&ch<='Z'){
			return ch-55;
		}else if(ch>='a'&&ch<='z'){
			return ch-87;
		}
		return -1;
	}

	static void aes_detail(int content[][],  int password[][]){
		int p[][][]=new int[11][4][4];
		keyExpansion(password, p);
		int encode = 1;
		addRoundKey(content, p[0]);
		for (int i = 1; i <= 10; ++i) {
			subBytes(content, encode);
			shiftRows(content, encode);
			if (i != 10) {
				mixColumns(content, encode);
			}
			addRoundKey(content, p[i]);
		}
	}

	static void subBytes(int a[][], int encode){
		// encode 为1 代表字节替代，为0代表逆向字节替代
		for (int i = 0; i < 4; ++i) {
			for (int j = 0; j < 4; ++j) {
				int temp = a[i][j] & 0xFF;
				int row = temp / 16;
				int column = temp % 16;
				if (encode==1)
					a[i][j] = S_BOX[row][column];
				else
					a[i][j] = INVERSE_S_BOX[row][column];
			}
		}
	}

	static void shiftRows(int a[][], int encode){
		//encode 为1代表行移位，为0代表逆向行移位
		for (int i = 0; i < 4; ++i) {
			for (int j = 0; j < i; ++j) {
				if (encode==1) {
					int temp = a[i][0];
					a[i][0] = a[i][1];
					a[i][1] = a[i][2];
					a[i][2] = a[i][3];
					a[i][3] = temp;
				} else{
					int temp = a[i][3];
					a[i][3] = a[i][2];
					a[i][2] = a[i][1];
					a[i][1] = a[i][0];
					a[i][0] = temp;
				}
			}
		}
	}

	static void mixColumns(int a[][], int encode){
		//encode 为1代表列混淆，为0代表逆向列混淆
		for (int i = 0; i < 4; ++i) {
			int temp0 = a[0][i];
			int temp1 = a[1][i];
			int temp2 = a[2][i];
			int temp3 = a[3][i];
			if (encode!=0) {
				a[0][i] = aes_multiple(temp0, 2) ^ aes_multiple(temp1, 3) ^ temp2 ^ temp3;
				a[1][i] = temp0 ^ (aes_multiple(temp1, 2)) ^ (temp2 ^ aes_multiple(temp2, 2)) ^ temp3;
				a[2][i] = temp0 ^ temp1 ^ (aes_multiple(temp2, 2)) ^ (temp3 ^ aes_multiple(temp3, 2));
				a[3][i] = temp0 ^ (aes_multiple(temp0, 2)) ^ temp1 ^ temp2 ^ aes_multiple(temp3, 2);
			}else{
				a[0][i] = aes_multiple(temp0, 14) ^ aes_multiple(temp1, 11) ^ aes_multiple(temp2, 13) ^ aes_multiple(temp3, 9);
				a[1][i] = aes_multiple(temp0, 9) ^ aes_multiple(temp1, 14) ^ aes_multiple(temp2, 11) ^ aes_multiple(temp3, 13);
				a[2][i] = aes_multiple(temp0, 13) ^ aes_multiple(temp1, 9) ^ aes_multiple(temp2, 14) ^ aes_multiple(temp3, 11);
				a[3][i] = aes_multiple(temp0, 11) ^ aes_multiple(temp1, 13) ^ aes_multiple(temp2, 9) ^ aes_multiple(temp3, 14);
			}
		}
	}

	static void addRoundKey(int a[][], int k[][]){
		// 由于用w[11][4][4]表示W[44]导致行列转置，所以在进行异或操作的时候应该是a[i，j] 异或 k[j,i]
		for (int i = 0; i < 4; ++i) {
			for (int j = 0; j < 4; ++j) {
				a[i][j] = a[i][j] ^ k[j][i];
			}
		}
	}

	//AES乘法计算
	static int aes_multiple(int a, int le){
		int thr = le & 0x8;
		int sec = le & 0x4;
		int fir = le & 0x2;
		int fir_mod = le % 2;
		int result = 0;
		if (thr!=0){
			int b = a;
			for (int i = 1; i <=3 ; ++i) {
				b = b<<1;
				if (b >= 256)
					b = b ^ 0x11b;
			}
			b = b % 256;
			result = result ^ b;
		}
		if (sec!=0){
			int b = a;
			for (int i = 1; i <=2 ; ++i) {
				b = b<<1;
				if (b >= 256)
					b = b ^ 0x11b;
			}
			b = b % 256;
			result = result ^ b;
		}
		if (fir!=0){
			int b = a << 1;
			if (b >= 256)
				b = b ^ 0x11b;
			b = b % 256;
			result = result ^ b;
		}
		if (fir_mod!=0)
			result = result ^ a;
		return  result;
	}

	static void keyExpansion(int key[][], int w[][][]){
		for (int i = 0; i < 4; ++i) {
			for (int j = 0; j < 4; ++j) {
				w[0][i][j] = key[j][i];
			}
		}
		for (int i = 1; i < 11; ++i){
			for (int j = 0; j < 4; ++j) {
				int temp[]=new int[4];
				if (j == 0){
					temp[0] = w[i-1][3][1];
					temp[1] = w[i-1][3][2];
					temp[2] = w[i-1][3][3];
					temp[3] = w[i-1][3][0];
					for (int k = 0; k < 4; ++k) {
						int m = temp[k];
						int row = m / 16;
						int column = m % 16;
						temp[k] = S_BOX[row][column];
						if (k == 0){
							temp[k] = temp[k] ^ RC[i-1];
						}
					}
				} else{
					temp[0] = w[i][j-1][0];
					temp[1] = w[i][j-1][1];
					temp[2] = w[i][j-1][2];
					temp[3] = w[i][j-1][3];
				}
				for (int l = 0; l < 4; ++l) {

					w[i][j][l] = w[i-1][j][l] ^ temp[l];
				}

			}
		}
	}

	//产生PIN码
	public static void createPinCode(byte [] vin, byte [] Pin,int Psize){
		//第一步，生成PIN
		Pin[0] = (byte) (vin[1] ^ vin[5] ^ vin[9]  ^ vin[13]);
		Pin[1] = (byte) (vin[2] ^ vin[6] ^ vin[10] ^ vin[14]);
		Pin[2] = (byte) (vin[3] ^ vin[7] ^ vin[11] ^ vin[15]);
		Pin[3] = (byte) (vin[4] ^ vin[8] ^ vin[12] ^ vin[16]);
	}

	//产生随机数
	public static byte [] createRandonAsc2Key(int mode,byte [] Pin,int len){
		byte [] v_buf = null;
		Random rand = new Random();
		if(len < 0) return v_buf;
		v_buf = new byte[len];
		if(mode == 0){ //由PIN码转换一组数据
			for(int i = 0; i < 4; i ++){
				v_buf[i * 4] = (byte) (0x30 + ((Pin[i]&0xFF) % 10));
				v_buf[i * 4 + 1] = (byte) (0x30 + (((Pin[i] >>> 2)&0xFF) % 10));
				v_buf[i * 4 + 2] = (byte) (0x30 + (((Pin[i] >>> 4)&0xFF) % 10));
				v_buf[i * 4 + 3] = (byte) (0x30 + (((Pin[i] >>> 6)&0xFF) % 10));
			}
		}else{
			v_buf[0] = (byte) (0x31 + rand.nextInt(8));
			for(int i = 1; i < len; i ++)
				v_buf[i] = (byte) (0x30 + rand.nextInt(9));
		}
		return v_buf;
	}

	public static void hongyuan_CreatePin(byte[] vin,byte[] pin){
		pin[0] = (byte) (((hongyuan_GetVinCode(vin[0]) + hongyuan_GetVinCode(vin[8]) + hongyuan_GetVinCode(vin[16])) % 16) * 0x10 +
				((hongyuan_GetVinCode(vin[1]) + hongyuan_GetVinCode(vin[8]) + hongyuan_GetVinCode(vin[15])) % 16));
		pin[1] = (byte) (((hongyuan_GetVinCode(vin[2]) + hongyuan_GetVinCode(vin[8]) + hongyuan_GetVinCode(vin[14])) % 16) * 0x10 +
				((hongyuan_GetVinCode(vin[3]) + hongyuan_GetVinCode(vin[8]) + hongyuan_GetVinCode(vin[13])) % 16));
		pin[2] = (byte) (((hongyuan_GetVinCode(vin[4]) + hongyuan_GetVinCode(vin[8]) + hongyuan_GetVinCode(vin[12])) % 16) * 0x10 +
				((hongyuan_GetVinCode(vin[5]) + hongyuan_GetVinCode(vin[8]) + hongyuan_GetVinCode(vin[11])) % 16));
		//pin[3] = (byte) (((hongyuan_GetVinCode(vin[6]) + hongyuan_GetVinCode(vin[8])) % 16) * 0x10 +
		//		((hongyuan_GetVinCode(vin[7]) + hongyuan_GetVinCode(vin[8])) % 16));
	}

	public static void hongyuan_CreateESK(byte[] vin,byte[] esk){
		byte [] bcSN = new byte[10];
		bcSN[0] = 'F';
		bcSN[1] = '1';
		bcSN[2] = 'A';
		int SN = (bcSN[0] + bcSN[1] + bcSN[2]) % 0x100;
		for(int j = 0; j < 16; j ++){
			if(j < 9)
				esk[j] = (byte) ((hongyuan_GetVinCode(vin[j]) + SN + hongyuan_GetVinCode(vin[9])) % 0x100);
			else
				esk[j] = (byte) ((hongyuan_GetVinCode(vin[j+1]) + SN + hongyuan_GetVinCode(vin[9])) % 0x100);
		}
	}

	private static int hongyuan_GetVinCode(byte P){
		int value = 0;
		if(P >= '0' && P <= '9')
			value = P - 0x30;
		else if(P >= 'A' && P <= 'H')
			value = P - 'A' + 10;
		else if(P >= 'J' && P <= 'N')
			value = P - 'J' + 18;
		else if(P =='P')
			value = 23;
		else if(P >= 'R' && P <= 'Z')
			value = P - 'R' + 24;
		else
			return 0;
		return value;
	}

	/**
	 * 根据VIN计算出PIN码
	 * @param Vin VIN码
	 * @param Pin pin字节数组
	 * @param Key 不同厂家对应的值
	 * @return 是否成功
	 */
	public static boolean generatePin(String Vin,byte [] Pin,String Key){
		if(Vin == null || Vin.length() != 17) return false;
		if(Key == null || Key.length() !=  8) return false;
		byte [] vintrip = new byte[8];
		byte [] pincode = new byte[8];
		//取VIN码后面8位
		System.arraycopy( Vin.getBytes(), 9,vintrip, 0, 8);
		Des_Go(pincode, vintrip, vintrip.length, Key, false);
		for(int i = 0; i < 4; i ++){
			Pin[i] = pincode[i * 2];
		}
		return true;
	}

	//DES
	private static boolean Des_Go(byte[] Pout,byte[] Pin,long datalen,String Key,boolean Type){
		if(((datalen+7) & 0xfffffff8) == 0) return false;
		SetKey(Key.getBytes(), Key.length());
		int outPos = 0;
		int inPos = 0;
		if(!Is3DES){// 1次DES
			long j = datalen >> 3;
			for(long i = 0; i < j; i ++){
				DES(Pout, outPos, Pin, inPos, SubKey, 0, Type);
				outPos += DESNUM;
				inPos += DESNUM;
			}
		}else{// 3次DES 加密:加(key0)-解(key1)-加(key0) 解密::解(key0)-加(key1)-解(key0)
			long j = datalen >> 3;
			for(long i = 0; i < j; i ++){
				DES(Pout, outPos, Pin, inPos, SubKey, 0, Type);
				DES(Pout, outPos, Pin, inPos, SubKey, 16*48, !Type);
				DES(Pout, outPos, Pin, inPos, SubKey, 0, Type);
				outPos += DESNUM;
				inPos += DESNUM;
			}
		}
		return true;
	}

	public static void SetKey(byte[] key,int len){
		deskey.clone();
		System.arraycopy(key, 0, deskey, 0, len > 16?16:len);
		SetSubKey(SubKey,0, deskey,0);
		if(len > 8){
			SetSubKey(SubKey,16*48,deskey,8);
			Is3DES = true;
		}else
			Is3DES = false;
	}

	public static void DES(byte[] Pout,int outPos,byte[] Pin,int PinPos,byte[] Psubkey,int subkeyPos,boolean type){
		byte[] M = new byte[64];
		byte[] tmp = new byte[32];
		//Li = M[0]   Ri = M[32]
		ByteToBit(M, 0, Pin, PinPos, 64);
		Transform(M, 0, M, 0, IP_Table, 64);
		if(type == false){
			for(int i = 0; i < 16; i ++){
				System.arraycopy(M, 32, tmp, 0, 32);
				F_func(M, 32,Psubkey,subkeyPos + i*48);
				Xor(M, 32, M, 0, 32);
				System.arraycopy(tmp, 0, M, 0, 32);
			}
		}else{
			for(int i = 15; i >= 0; i --){
				System.arraycopy(M, 0, tmp, 0, 32);
				F_func(M, 0,Psubkey,subkeyPos + i);
				Xor(M, 0, M, 32, 32);
				System.arraycopy(tmp, 0, M, 32, 32);
			}
		}
		Transform(M, 0, M, 0, IPR_Table, 64);
		BitToByte(Pout, outPos, M, 0, 64);
	}

	public static void SetSubKey(byte[] Pkey,int PkeyPos,byte[] Key,int keyPos){
		byte[] K = new byte[64];
		//KL  --k[0]  ; KR = k[28]
		ByteToBit(K, 0, Key, keyPos, 64);
		Transform(K,0, K,0, PC1_Table, 56);
		for(int i = 0; i < 16; i ++){
			RotateL(K, 0 , 28, LOOP_Table[i]);
			RotateL(K, 28, 28, LOOP_Table[i]);
			Transform(Pkey,PkeyPos + i * 48, K,0, PC2_Table, 48);
		}
	}

	public static void F_func(byte[] Pin,int PinPos,byte[] Pki,int PkiPos){
		byte[] MR = new byte[48];
		Transform(MR,0, Pin, PinPos,E_Table, 48);
		Xor(MR,0,Pki,PkiPos,48);
		S_func(Pin,PinPos, MR,0);
		Transform(Pin,PinPos,Pin, PinPos,P_Table,32);
	}

	public static void S_func(byte[] Pout,int PoutPos,byte[] Pin,int PinPos){
		byte j,k;
		int InAdd = PinPos;
		int OutAdd = PoutPos;
		for(int i = 0; i < 8; i ++){
			j = (byte) ((Pin[InAdd + 0] << 1) + Pin[InAdd + 5]);
			k = (byte) ((Pin[InAdd + 1] << 3) + (Pin[InAdd + 2] << 2) + (Pin[InAdd + 3] << 1) +  + Pin[InAdd + 4]);
			ByteToBit(Pout,OutAdd,S_Box,i*64 +j*16 + k,4);
			InAdd += 6;
			OutAdd += 4;
		}
	}
	public static void Transform(byte[] Pout,int Pstart,byte[] Pin,int PinPos,byte[] Table,int Plen){
		for(int i = 0; i < Plen; i ++)
			Tmp[i] = (byte)Pin[PinPos + (Table[i] & 0xFF) - 1];
		System.arraycopy(Tmp, 0, Pout, Pstart, Plen);
	}

	public static void Xor(byte[] InA,int InAPos,byte[] InB,int InBPos,int Plen){
		for(int i = 0; i < Plen; i ++)
			InA[InAPos + i] ^= InB[InBPos + i];
	}

	public static void RotateL(byte[] Pin,int Pstart,int Plen,int loop){
		System.arraycopy( Pin, Pstart,Tmp, 0, loop);
		System.arraycopy( Pin, Pstart + loop,Pin, Pstart, Plen - loop);
		System.arraycopy( Tmp, 0,Pin, Pstart + Plen - loop, loop);
	}

	public static void ByteToBit(byte[] Pout,int outPos,byte[] Pin,int inPos,int bits){
		for(int i = 0; i < bits; i ++)
			Pout[outPos + i] = (byte) ((Pin[inPos + (i >> 3)] >> (i&7)) & 0x01);
	}

	public static void BitToByte(byte[] Pout,int outPos,byte[] Pin,int PinPos,int bits){
		Pout.clone();
		for(int i = 0; i < bits; i ++)
			Pout[outPos + i >> 3] |= Pin[PinPos + i] << (i&7);
	}

}
